package top.hekun.study.core;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import top.hekun.study.core.util.ClassFileUtil;
import top.hekun.study.core.visitor.method.complex.*;

import java.io.File;
import java.util.Arrays;

/**
 * 〈复杂的变换修改〉
 *  类复杂修改方法代码演示
 * @author: Sakura
 * @date: 2023/5/12 21:25
 */
public class ClassComplexModifyMethodCodeDemo {
    public static void main(String[] args) {
        byte[] classBytes = ClassFileUtil.getClassFileByteToClassName("HelloWordComplex");
        ClassReader classReader = new ClassReader(classBytes);
        System.out.println("access > " + classReader.getAccess());
        System.out.println("className > " + classReader.getClassName());
        System.out.println("classSuperName > " + classReader.getSuperName());
        System.out.println("Interfaces > " + Arrays.toString(classReader.getInterfaces()));
        System.out.println();


        // 类编写器
        ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        int apiVersion = Opcodes.ASM9;
        ClassVisitor classVisitor0 = new MyClassVisitorComplexCode0(apiVersion, classWriter);
        // 清除 +0 类的 代码
        ClassVisitor classVisitor1 = new MyClassVisitorComplexCode1(apiVersion, classVisitor0);
        // 清除 var = var 自己赋值给自己进行处理
        ClassVisitor classVisitor2 = new MyClassVisitorComplexCode2(apiVersion, classVisitor1);
        // 清除打印输出语句
        ClassVisitor classVisitor3 = new MyClassVisitorComplexCode3(apiVersion, classVisitor2);

        // 添加 java8 的Lambda 表达式
        ClassVisitor  classVisitor4 = new MyClassVisitorComplexCode4(apiVersion, classVisitor3);
        // 运行的时候 方法倒序调用 6>5>4>3>2>1
        classReader.accept(classVisitor4, ClassReader.EXPAND_FRAMES | ClassReader.SKIP_DEBUG);
        byte[] classByte = classWriter.toByteArray();
        writeClassFileCore(classByte, getClassFile());
    }

    private static File getClassFile() {
        String className = "HelloWordComplexModifyClass";
        File file = new File(ClassFileUtil.getClassFileModelPath(), className + ".class");
        return file;
    }

    private static void writeClassFileCore(byte[] core, File classFilePath) {
        ClassFileUtil.classFileCoreWrite(core, classFilePath);
    }

}
